/* 
 * Advanced Foundation Classes
 * Copyright (C) 2000/2004  Fabio Rotondo - Andrea Galimberti
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "clist.h"

// {{{ defines
static EGCListData * afc_easygui_internal_clist_data_new ( EasyGUI * egui, char * cols, char * alignment, char * sizes );
static int afc_easygui_internal_clist_data_delete ( EGCListData * cldata );
static int afc_easygui_internal_clist_get_template ( DynamicClass * dyn );
static int afc_easygui_internal_cb_clist ( DynamicClass * dyn );

// METHODS
static int afc_easygui_clist_method_add ( DynamicClass * dyn );
static int afc_easygui_clist_method_set_titles ( DynamicClass * dyn );
static int afc_easygui_clist_method_clear ( DynamicClass * dc );
static int afc_easygui_clist_method_set_fore_color ( DynamicClass * dc );
static int afc_easygui_clist_method_set_back_color ( DynamicClass * dc );
static int afc_easygui_clist_method_select ( DynamicClass * dyn );
static int afc_easygui_clist_method_block ( DynamicClass * dyn );
static int afc_easygui_clist_method_unblock ( DynamicClass * dyn );
static int afc_easygui_clist_method_add_fast ( DynamicClass * dyn );

static int afc_easygui_clist_method_get_attr ( DynamicClass * dc );
static int afc_easygui_clist_method_set_attr ( DynamicClass * dc );

// EVENTS
static void afc_easygui_clist_event_row_selected ( GtkWidget * wid, gint row, gint column, GdkEvent * ev, gpointer data );
static void afc_easygui_clist_event_row_unselected ( GtkWidget * wid, gint row, gint column, GdkEvent * ev, gpointer data );
static void afc_easygui_clist_event_row_sel_unsel ( GtkWidget * w, gint row, short selected, GdkEvent * ev, gpointer data );
static gboolean afc_easygui_clist_event_activated ( GtkWidget * w, GdkEvent * e, gpointer data );
static void afc_easygui_clist_event_column_clicked ( GtkWidget * w, gint column, gpointer data );

// INTERNAL FUNCTIONS
static void afc_easygui_internal_clist_set_selmode ( EasyGUI * egui, EGCListData * cldata, char * selmode );
static void afc_easygui_clist_internal_set_color ( DynamicClass * dc, int mode );
// }}}

static const char class_name[] = "Widget CList";

// {{{ afc_easygui_internal_clist_new_instance ()
/*
@node afc_easygui_internal_clist_new_instance

@endnode
*/
DynamicClass * afc_easygui_internal_clist_new_instance ()
{
	DynamicClass * dyn = NULL;

	if ( ( dyn = afc_dynamic_class_new () ) == NULL ) 
	{
		AFC_LOG_FAST ( AFC_ERR_NO_MEMORY );
		return ( NULL );
	}

	afc_dynamic_class_add_method ( dyn, "get_template", 	NULL,	afc_easygui_internal_clist_get_template );
	afc_dynamic_class_add_method ( dyn, "open_callback", 	NULL,	afc_easygui_internal_cb_clist );
	afc_dynamic_class_add_method ( dyn, "enabled",	NULL, 	afc_easygui_widget_method_enabled );

	afc_dynamic_class_add_method ( dyn, "add", 		NULL,  	afc_easygui_clist_method_add );
	afc_dynamic_class_add_method ( dyn, "set_titles", 	NULL,  	afc_easygui_clist_method_set_titles );
	afc_dynamic_class_add_method ( dyn, "clear", 		NULL,   afc_easygui_clist_method_clear );
	afc_dynamic_class_add_method ( dyn, "set_fore_color", 	NULL,  	afc_easygui_clist_method_set_fore_color );
	afc_dynamic_class_add_method ( dyn, "set_back_color", 	NULL, 	afc_easygui_clist_method_set_back_color );
	afc_dynamic_class_add_method ( dyn, "select", 		NULL, 	afc_easygui_clist_method_select );
	afc_dynamic_class_add_method ( dyn, "block", 		NULL, 	afc_easygui_clist_method_block );
	afc_dynamic_class_add_method ( dyn, "unblock", 		NULL, 	afc_easygui_clist_method_unblock );
	afc_dynamic_class_add_method ( dyn, "add_fast", 	NULL,	afc_easygui_clist_method_add_fast );

	afc_dynamic_class_add_method ( dyn, "set_attr", 	NULL,	afc_easygui_clist_method_set_attr );
	afc_dynamic_class_add_method ( dyn, "get_attr", 	NULL,	afc_easygui_clist_method_get_attr );

	// afc_dynamic_class_add_method ( dyn, "set_list", NULL,    afc_easygui_clist_method_set_list );

	return ( dyn );
}
// }}}
// {{{ afc_easygui_internal_clist_del_instance ( dyn )
/*
@node afc_easygui_internal_clist_del_instance

@endnode
*/
int afc_easygui_internal_clist_del_instance ( DynamicClass * dyn )
{
	EGCListData * cldata;
	
	if ( dyn == NULL ) return ( AFC_LOG_FAST ( AFC_ERR_NULL_POINTER ) );

	// Avoid the warning by checking that the "vars" Dictionary has been created
	//if ( dyn->vars == NULL ) return ( AFC_ERR_NO_ERROR );

	if ( dyn->vars != NULL ) {
		AFC_CLIST_GET_CLDATA ( dyn, cldata );

		if ( cldata ) afc_easygui_internal_clist_data_delete ( cldata );
	}

	return ( afc_easygui_widget_standard_free ( dyn ) );
}
// }}}
// {{{ afc_easygui_internal_clist_get_template ( dyn )
/*
@node afc_easygui_internal_clist_get_template
	
@endnode

	COLUMNS		- Eg. "Col 1|Col 2|Column 3"
	SELMODE		- SINGLE|BROWSE|MULTI
	SIZES		- 100|20|80|...
	ALIGNMENT	- LEFT|RIGHT|CENTER
	NOTITLES/S	- If set, the CList will have no titles

	ACTIVATED	- Row Double Clicked event
	CHANGED		- Row changed its status event
	SELECTED	- Row selected event (fired BEFORE the row actually changed state)
*/
static int afc_easygui_internal_clist_get_template ( DynamicClass * dyn )
{
	dyn->result = "COLUMNS/A SELMODE/K NOTITLES/S ALIGNMENT/K SIZES/K ACTIVATED/K CHANGED/K CLICKCOLUMN/K DRAGGET/K DRAGSET/K";
	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_internal_cb_clist ( dyn )
/*
@node afc_easygui_internal_cb_clist

@endnode
*/
static int afc_easygui_internal_cb_clist ( DynamicClass * dyn )
{
	EasyGUI * egui = dyn->info;
	EasyGUIContext * context = egui->curr_context;
	EGCListData * cldata;
	char * columns, * selmode, * alignment, * sizes;
	char * activated, * changed, * clickcolumn, * dndset, * dndget;
	BOOL  notitles;
	int afc_res = AFC_ERR_NO_ERROR;
	DynamicClass * dc;

	if ( context->curr_container == NULL ) return ( AFC_EASYGUI_ERR_NO_CONTAINER );

	afc_easygui_widget_parse_default_params ( egui );

	columns     = afc_cmd_parser_arg_get_by_name ( egui->parser, "COLUMNS" );
	selmode     = afc_cmd_parser_arg_get_by_name ( egui->parser, "SELMODE" );
	alignment   = afc_cmd_parser_arg_get_by_name ( egui->parser, "ALIGNMENT" ); 
	activated   = afc_cmd_parser_arg_get_by_name ( egui->parser, "ACTIVATED" );
	changed     = afc_cmd_parser_arg_get_by_name ( egui->parser, "CHANGED" );
	clickcolumn = afc_cmd_parser_arg_get_by_name ( egui->parser, "CLICKCOLUMN" );
	sizes	    = afc_cmd_parser_arg_get_by_name ( egui->parser, "SIZES" );
	dndset      = afc_cmd_parser_arg_get_by_name ( egui->parser, "DRAGSET" );
	dndget      = afc_cmd_parser_arg_get_by_name ( egui->parser, "DRAGGET" );

	notitles  = ( BOOL ) ( int ) afc_cmd_parser_arg_get_by_name ( egui->parser, "NOTITLES" );

	if ( ( dc = afc_dynamic_class_master_new_instance ( egui->commands, "clist" ) ) == NULL )
		return ( AFC_LOG_FAST_INFO ( AFC_ERR_NO_MEMORY, "dynclass instance" ) );

	WIDGET_SET_CONTEXT ( dc, context );

	if ( ( cldata = afc_easygui_internal_clist_data_new ( egui, columns, alignment, sizes ) ) == NULL )
		return ( AFC_LOG_FAST_INFO ( AFC_ERR_NO_MEMORY, "cldata" ) );

	if ( ( afc_res = afc_easygui_internal_add_widget ( context, cldata->scrollwin, dc ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );


	if ( notitles ) 
		gtk_clist_column_titles_hide ( GTK_CLIST ( cldata->clist ) );
	else
		gtk_clist_column_titles_show ( GTK_CLIST ( cldata->clist ) );

	afc_easygui_internal_clist_set_selmode ( egui, cldata, selmode );

	// Set the Widget data for the Dynamic Class
	AFC_CLIST_STORE_DYNCLASS ( cldata->clist, dc );

	// Store the cldata struct inside a DynClass data
	afc_dynamic_class_set_var ( dc, AFC_DYNAMIC_CLASS_VAR_KIND_POINTER, "cldata", cldata );

	// Sets an internal array value to know the Dynamic Class
	// AFC_CLIST_STORE_DYNCLASS ( cldata->view, dc );

	// ------------------------------------------------------------------------------------------------
	// Sets the default signal handlers
	// ------------------------------------------------------------------------------------------------
	afc_easygui_widget_add_default_events ( context, dc, cldata->clist );

	// Row Selected
	if ( changed )
	{
		if ( ( afc_res = afc_easygui_widget_connect_signal ( dc, cldata->clist, "select_row", changed, NULL, (GtkSignalFunc) afc_easygui_clist_event_row_selected ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );

		// Row Unselected
		if ( ( afc_res = afc_easygui_widget_connect_signal ( dc, cldata->clist, "unselect_row", changed, NULL, (GtkSignalFunc) afc_easygui_clist_event_row_unselected ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );
	} else {
		g_signal_connect ( cldata->clist, "select_row", G_CALLBACK ( afc_easygui_clist_event_row_selected ), dc );
		g_signal_connect ( cldata->clist, "unselect_row", G_CALLBACK ( afc_easygui_clist_event_row_unselected ), dc );
	}

	// Row double click
	if ( ( afc_res = afc_easygui_widget_connect_signal ( dc, cldata->clist, "button_press_event", activated, NULL, (GtkSignalFunc) afc_easygui_clist_event_activated ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );

	// Column Clicked
	if ( ( afc_res = afc_easygui_widget_connect_signal ( dc, cldata->clist, "click-column", clickcolumn, NULL, (GtkSignalFunc) afc_easygui_clist_event_column_clicked ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );

	// DND SET
	if ( ( afc_res = afc_easygui_widget_dnd_dest_connect ( dc, cldata->clist, dndset ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );
	
	// DND GET
	if ( ( afc_res = afc_easygui_widget_dnd_source_connect ( dc, cldata->clist, dndget ) ) != AFC_ERR_NO_ERROR ) return ( afc_res );

	return ( afc_res );
}
// }}}
// {{{ afc_easygui_internal_clist_data_new ( egui, cols, alignment, colsizes )
static EGCListData * afc_easygui_internal_clist_data_new ( EasyGUI * egui, char * cols, char * alignment, char * colsizes )
{
	EGCListData * cldata = afc_malloc ( sizeof ( EGCListData ) );
	char * s, * al;
	int t;
	StringNode * split = NULL;
	int data;

	if ( cldata == NULL ) 
	{
		AFC_LOG_FAST_INFO ( AFC_ERR_NO_MEMORY, "cldata" );
		return ( NULL );
	}

	cldata->current_row = -1;

	if ( alignment || colsizes )
	{
		if ( ( split = afc_stringnode_new () ) == NULL )
		{
			afc_free ( cldata );
			AFC_LOG_FAST_INFO ( AFC_ERR_NO_MEMORY, "split" );
			return ( NULL );
		}
	}

	if ( cols == NULL ) cols = "Title";	// Fallback to avoid errors

	afc_stringnode_split ( egui->int_data->snode, cols, egui->int_data->delimiters );

	cldata->columns = afc_stringnode_len ( egui->int_data->snode );

	// Create the ScrollWindow (the main container)
	cldata->scrollwin = gtk_scrolled_window_new ( NULL, NULL );
	gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( cldata->scrollwin ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );

	cldata->clist = gtk_clist_new ( cldata->columns );
	gtk_widget_show ( cldata->clist );

	// Add View to the Scrolled Window
	gtk_container_add ( GTK_CONTAINER ( cldata->scrollwin ), cldata->clist );


	// Creates the columns
	for ( t = 0; t < cldata->columns; t ++ )
	{
		if ( ( s = afc_stringnode_item ( egui->int_data->snode, t ) ) != NULL ) 
		{
			gtk_clist_set_column_title ( GTK_CLIST ( cldata->clist ), t, s );
		}

	}

	// Parses the aligns string
	if ( alignment )
	{
		afc_stringnode_split ( split, alignment, egui->int_data->delimiters );
		for ( t = 0; t < cldata->columns; t++ )
		{
			if ( ( al = afc_stringnode_item ( split, t ) ) != NULL )
			{
				data = GTK_JUSTIFY_LEFT;
				if ( strcasecmp ( al, "CENTER" ) == 0 )    data = GTK_JUSTIFY_CENTER;
				else if ( strcasecmp (al, "RIGHT" ) == 0 ) data = GTK_JUSTIFY_RIGHT;
				else if ( strcasecmp (al, "FILL" ) == 0 )  data = GTK_JUSTIFY_FILL;

				gtk_clist_set_column_justification ( GTK_CLIST ( cldata->clist ), t, data );
			}
		}
	}

	// Parses the colsizes string
	if ( colsizes )
	{
		afc_stringnode_split ( split, colsizes, egui->int_data->delimiters );
		for ( t = 0; t < cldata->columns; t++ )
		{
			if ( ( al = afc_stringnode_item ( split, t ) ) != NULL )
			{
				data = atoi ( al );

				gtk_clist_set_column_width ( GTK_CLIST ( cldata->clist ), t, data );
			}
		}
	}

	// Deletes the align splitter class
	if ( split ) afc_stringnode_delete ( split );
	

	return ( cldata );
}
// }}}
// {{{ afc_easygui_internal_clist_data_delete ( cldata )
static int afc_easygui_internal_clist_data_delete ( EGCListData * cldata )
{
	if ( cldata == NULL ) return ( AFC_LOG_FAST ( AFC_ERR_NULL_POINTER ) );

	afc_free ( cldata );

	return ( AFC_ERR_NO_ERROR );
}
// }}}

// ------------------------------------------------------------------------------------------------------------------------
// CList Methods
// ------------------------------------------------------------------------------------------------------------------------
// {{{ afc_easygui_clist_method_select ( dyn )
static int afc_easygui_clist_method_select ( DynamicClass * dyn )
{
	EGCListData * cldata;
	int row;
	int mode;
	
	AFC_CLIST_GET_CLDATA ( dyn, cldata );

	row  = ( int ) afc_array_master_item ( dyn->args, 0 );
	mode = ( int ) afc_array_master_item ( dyn->args, 1 );

	if ( row == AFC_EASYGUI_CLIST_LAST_ROW )	row = cldata->rows -1;	// The last row set
	
	if ( mode == AFC_EASYGUI_CLIST_SELECT )	// Select
		if ( row == AFC_EASYGUI_CLIST_ALL_ROWS )	// all
			gtk_clist_select_all ( GTK_CLIST ( cldata->clist ) );
		else
			gtk_clist_select_row ( GTK_CLIST ( cldata->clist ), row, 1 );
	else			// Unselect
		if ( row == AFC_EASYGUI_CLIST_ALL_ROWS )	// all
			gtk_clist_unselect_all ( GTK_CLIST ( cldata->clist ) );
		else
			gtk_clist_unselect_row ( GTK_CLIST ( cldata->clist ), row, 1 );
	
	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_add ( dyn )
static int afc_easygui_clist_method_add ( DynamicClass * dyn )
{
	char * s;
	EasyGUIWidgetData * ewidget;
	EGCListData * cldata;
	int t = 0;
	char * * items;
	void * info;

	WIDGET_GET_EWIDGET ( dyn, ewidget );
	AFC_CLIST_GET_CLDATA ( dyn, cldata );	

	gtk_clist_freeze ( GTK_CLIST ( cldata->clist ) );

	items = afc_malloc ( ( sizeof ( char * ) ) * afc_array_master_len ( dyn->args ) );

	afc_array_master_last ( dyn->args );		// This is the AFC_EASYGUI_ARG_END
	info = afc_array_master_prev ( dyn->args );	// This is the info field
	afc_array_master_del ( dyn->args );		// Remove the info field

	s = afc_array_master_first ( dyn->args );
	while ( s != AFC_EASYGUI_ARG_END ) 
	{
		items [ t++ ] = s;
		s = afc_array_master_next ( dyn->args );
	}

	gtk_clist_append ( GTK_CLIST ( cldata->clist ), items );

	gtk_clist_set_foreground ( GTK_CLIST ( cldata->clist ), cldata->rows, &cldata->fore_color );
	gtk_clist_set_background ( GTK_CLIST ( cldata->clist ), cldata->rows, &cldata->back_color );

	gtk_clist_set_row_data	 ( GTK_CLIST  ( cldata->clist ), cldata->rows, info );

	gtk_clist_thaw ( GTK_CLIST ( cldata->clist ) );

	cldata->rows ++;

	afc_free ( items );

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_add_fast ( dyn )
static int afc_easygui_clist_method_add_fast ( DynamicClass * dyn )
{
	char * s;
	EasyGUIWidgetData * ewidget;
	EGCListData * cldata;
	int t = 0;
	char * * items;
	void * info;

	WIDGET_GET_EWIDGET ( dyn, ewidget );
	AFC_CLIST_GET_CLDATA ( dyn, cldata );	

	items = afc_malloc ( ( sizeof ( char * ) ) * afc_array_master_len ( dyn->args ) );

	afc_array_master_last ( dyn->args );		// This is the AFC_EASYGUI_ARG_END
	info = afc_array_master_prev ( dyn->args );	// This is the info field
	afc_array_master_del ( dyn->args );		// Remove the info field

	s = afc_array_master_first ( dyn->args );
	while ( s != AFC_EASYGUI_ARG_END ) 
	{
		items [ t++ ] = s;
		s = afc_array_master_next ( dyn->args );
	}

	gtk_clist_append ( GTK_CLIST ( cldata->clist ), items );

	gtk_clist_set_foreground ( GTK_CLIST ( cldata->clist ), cldata->rows, &cldata->fore_color );
	gtk_clist_set_background ( GTK_CLIST ( cldata->clist ), cldata->rows, &cldata->back_color );

	gtk_clist_set_row_data	 ( GTK_CLIST  ( cldata->clist ), cldata->rows, info );

	cldata->rows ++;

	afc_free ( items );

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_block ( dyn )
static int afc_easygui_clist_method_block ( DynamicClass * dyn )
{
	EGCListData * cldata;

	AFC_CLIST_GET_CLDATA ( dyn, cldata );	

	gtk_clist_freeze ( GTK_CLIST ( cldata->clist ) );

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_unblock ( dyn )
static int afc_easygui_clist_method_unblock ( DynamicClass * dyn )
{
	EGCListData * cldata;

	AFC_CLIST_GET_CLDATA ( dyn, cldata );	

	gtk_clist_thaw ( GTK_CLIST ( cldata->clist ) );

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_set_titles ( dyn )
static int afc_easygui_clist_method_set_titles ( DynamicClass * dyn )
{
	EGCListData * cldata;
	int t = 0;
	char * s;

	AFC_CLIST_GET_CLDATA ( dyn, cldata );	

	s = afc_array_master_first ( dyn->args );
	while ( ( s != NULL ) && ( s != AFC_EASYGUI_ARG_END ) )
	{
		gtk_clist_set_column_title ( GTK_CLIST ( cldata->clist ), t, s );

		t++;
		s = afc_array_master_next ( dyn->args );
	}
	
	
	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_get_attr ( dyn )
// Gets an attr from the widget
static int afc_easygui_clist_method_get_attr ( DynamicClass * dc )
{
	char * * buffer;
	int	 attr;
	EGCListData * cldata;
	EasyGUIWidgetData * ewidget;

	WIDGET_GET_EWIDGET ( dc, ewidget );
	AFC_CLIST_GET_CLDATA ( dc, cldata );	

	attr 	= ( int ) afc_array_master_first ( dc->args );
	buffer 	= ( char * * ) afc_array_master_next ( dc->args );

	switch ( attr )
	{
		case AFC_EASYGUI_WIDGET_ATTR_VALUE:
			dc->result = ( void * ) gtk_entry_get_text ( GTK_ENTRY ( ewidget->gtk_handle ) );		
			*buffer = ( char * ) dc->result;
			break;

		case AFC_EASYGUI_WIDGET_ATTR_NAME:
			dc->result = ( void * ) gtk_widget_get_name ( GTK_WIDGET ( ewidget->gtk_handle ) );
			*buffer = ( char * ) dc->result;
			break;

		default:
			AFC_LOG_FAST ( AFC_ERR_UNSUPPORTED_TAG );
	}

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_set_attr ( dyn )
// Sets an attr value to the widget
static int afc_easygui_clist_method_set_attr ( DynamicClass * dc )
{
	char * buffer;
	int	 attr;
	EGCListData * cldata;
	EasyGUIWidgetData * ewidget;

	WIDGET_GET_EWIDGET ( dc, ewidget );
	AFC_CLIST_GET_CLDATA ( dc, cldata );	

	attr 	= ( int ) afc_array_master_first ( dc->args );
	buffer 	= ( char * ) afc_array_master_next ( dc->args );

	switch ( attr )
	{
		case AFC_EASYGUI_WIDGET_ATTR_VISIBLE:
			g_object_set ( G_OBJECT ( ewidget->gtk_handle ), "visible", ( gboolean ) ( int ) buffer, NULL, NULL );
			break;

		case AFC_EASYGUI_WIDGET_ATTR_ACTIVE:
			g_object_set ( G_OBJECT ( ewidget->gtk_handle ), "sensitive", ( gboolean ) ( int ) buffer, NULL, NULL );
			break;

		case AFC_EASYGUI_WIDGET_ATTR_FOCUS:
			gtk_widget_grab_focus ( GTK_WIDGET ( ewidget->gtk_handle ) );
			break;

		case AFC_EASYGUI_WIDGET_ATTR_NAME:
			gtk_widget_set_name ( GTK_WIDGET ( ewidget->gtk_handle ), ( const char * ) buffer );
			break;

		case AFC_EASYGUI_CLIST_ATTR_SHOW_TITLES:
			if ( ( int ) buffer )
				gtk_clist_column_titles_show ( GTK_CLIST ( cldata->clist ) );
			else
				gtk_clist_column_titles_hide ( GTK_CLIST ( cldata->clist ) );
			break;

		default:
			fprintf ( stderr, "CLIST: unsupported attr\n" );
	}

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_clear ( dyn )
static int afc_easygui_clist_method_clear ( DynamicClass * dc )
{
	EGCListData * cldata;

	AFC_CLIST_GET_CLDATA ( dc, cldata );	

	gtk_clist_clear ( GTK_CLIST ( cldata->clist ) );

	cldata->rows = 0;
	cldata->current_row = -1;

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_set_fore_color ( dyn )
static int afc_easygui_clist_method_set_fore_color ( DynamicClass * dc )
{
	afc_easygui_clist_internal_set_color ( dc, 0 );

	return ( AFC_ERR_NO_ERROR );
}
// }}}
// {{{ afc_easygui_clist_method_set_back_color ( dyn )
static int afc_easygui_clist_method_set_back_color ( DynamicClass * dc )
{
	afc_easygui_clist_internal_set_color ( dc, 1 );

	return ( AFC_ERR_NO_ERROR );
}

// ------------------------------------------------------------------------------------------------------------------------
// EVENT FUNCTIONS
// ------------------------------------------------------------------------------------------------------------------------
// {{{ afc_easygui_clist_event_row_selected ( wid, row, column, ev, data )
static void afc_easygui_clist_event_row_selected ( GtkWidget * wid, gint row, gint column, GdkEvent * ev, gpointer data )
{
	afc_easygui_clist_event_row_sel_unsel ( wid, row, TRUE, ev, data );
}
// }}}
// {{{ afc_easygui_clist_event_row_unselected ( wid, row, column, ev, data )
static void afc_easygui_clist_event_row_unselected ( GtkWidget * wid, gint row, gint column, GdkEvent * ev, gpointer data )
{
	afc_easygui_clist_event_row_sel_unsel ( wid, row, FALSE, ev, data );
}
// }}}
// {{{ afc_easygui_clist_event_row_sel_unsel ( w, row, ev, data )
static void afc_easygui_clist_event_row_sel_unsel ( GtkWidget * w, gint row, short selected, GdkEvent * ev, gpointer data )
{
	DynamicClass * dc;
	EasyGUICListSelectSignalFunc sig;
	EGCListData * cldata;
	char * s;

	AFC_CLIST_GET_DYNCLASS ( w, dc );
	AFC_CLIST_GET_CLDATA ( dc, cldata );

	cldata->current_row = row;

	if ( selected )
		s = "select_row";
	else
		s = "unselect_row";

	WIDGET_GET_CALLBACK_CAST ( dc, s, sig, EasyGUICListSelectSignalFunc );

	data = gtk_clist_get_row_data ( GTK_CLIST ( w ), row );
	sig ( dc, WIDGET_GET_CONTEXT ( dc ), selected, data );
}
// }}}
// {{{ afc_easygui_clist_event_activated ( w, e, data )
static gboolean afc_easygui_clist_event_activated ( GtkWidget * w, GdkEvent * e, gpointer data )
{
	EGCListData * cldata;
	DynamicClass * dc;
	EasyGUICListSignalFunc sig;

	AFC_CLIST_GET_DYNCLASS ( w, dc );
	AFC_CLIST_GET_CLDATA ( dc, cldata );

	
	if ( e->type == 4 ) return ( false );			// The user is not double clicking

	// printf ( "Button press event...%d - cldata->current_row: %d\n", e->type, cldata->current_row );
	if ( cldata->current_row == -1 ) return ( false );	// No row is actually selected

	// Stop signal propagation
	//gtk_signal_emit_stop_by_name ( GTK_OBJECT ( cldata->clist ), "button_press_event" );

	// printf ( "Double Click!\n" );

	if ( ( sig = ( EasyGUICListSignalFunc ) afc_dictionary_get ( dc->private_vars, "button_press_event" ) ) == NULL ) return ( false );

	data = gtk_clist_get_row_data ( GTK_CLIST ( w ), cldata->current_row );
	sig ( dc, WIDGET_GET_CONTEXT ( dc ), data );

	return ( true );
}
// }}}
// {{{ afc_easygui_clist_event_column_clicked ( w, column, data )
static void afc_easygui_clist_event_column_clicked ( GtkWidget * w, gint column, gpointer data )
{
	EGCListData * cldata;
	DynamicClass * dc;
	EasyGUICListColumnClickedFunc sig;

	AFC_CLIST_GET_DYNCLASS ( w, dc );
	AFC_CLIST_GET_CLDATA ( dc, cldata );

	if ( ( sig = ( EasyGUICListColumnClickedFunc ) afc_dictionary_get ( dc->private_vars, "click-column" ) ) == NULL ) return;

	data = gtk_clist_get_row_data ( GTK_CLIST ( w ), cldata->current_row );
	sig ( dc, WIDGET_GET_CONTEXT ( dc ), column, data );
}
// }}}

// ------------------------------------------------------------------------------------------------------------------------
// INTERNALS
// ------------------------------------------------------------------------------------------------------------------------
// {{{ afc_easygui_internal_clist_set_selmode ( egui, cldata, selmode )
static void afc_easygui_internal_clist_set_selmode ( EasyGUI * egui, EGCListData * cldata, char * selmode )
{
	int mode;

	if ( selmode == NULL ) return;

	if ( strcasecmp ( selmode, "BROWSE" ) == 0 ) 		mode = GTK_SELECTION_BROWSE;
	else if ( strcasecmp ( selmode, "MULTI" ) == 0 ) 	mode = GTK_SELECTION_MULTIPLE;
	else mode = GTK_SELECTION_SINGLE;

	gtk_clist_set_selection_mode ( GTK_CLIST ( cldata->clist ), mode );
}
// }}}
// {{{ afc_easygui_clist_internal_set_color ( dyn, mode )
static void afc_easygui_clist_internal_set_color ( DynamicClass * dyn, int mode )
{
	GdkColor * col;
	EGCListData * cldata;
	int red, green, blue;

	AFC_CLIST_GET_CLDATA ( dyn, cldata );

	if ( mode == 0 )
		col = &cldata->fore_color;
	else
		col = &cldata->back_color;

	red   = ( int ) afc_array_master_item ( dyn->args, 0 );
	green = ( int ) afc_array_master_item ( dyn->args, 1 );
	blue  = ( int ) afc_array_master_item ( dyn->args, 2 );

        col->red   = red     * 255;
        col->green = green   * 255;
        col->blue  = blue    * 255;

        col->pixel = (gulong) (red *65535 + green*256 + blue);
}
// }}}
